package CPU;

import action.ProcessHistory;
import controller.ScheduiUIController;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import memory.Memory;
import memory.MemoryDispatcher;
import process.PCB;
import process.ProcessDispatcher;

import java.util.Map;

import static process.ProcessDispatcher.awakeProcess;
import static process.ProcessDispatcher.destroyProcess;

public class CPU {
    private static final long serialVersionUID = 1L;
    public static int PC;
    public static int PSW;
    public static PCB pcb;
    public static String Instruction = new String();
    public static String resultString = new String();
    public static volatile boolean WakedUP = false;
    public static final int NONE_INTERMIT = 0;  //无中断
    public static final int TIME_INTERMIT = 1;  //时间片到中断
    public static final int NORMAL_INTERMIT = 2;  //正常中断
    public static final int EQUIP_INTERMIT = 3;   //设备中断
    public static final char[] IR = new char[3]; //指令寄存器
    public static ScheduiUIController UI_CONTROLLER;
    private static int timeSize = 6;   //时间片大小
    private volatile static CPU cpu;


    public static CPU getInstance() {
        if (cpu == null) {
            synchronized (CPU.class) {
                if (cpu == null) {
                    cpu = new CPU();
                }
            }
        }
        return cpu;
    }

    public static void run() {
//        时间片
        int time = timeSize;

        while (true) {
//            如果进程分配器正在执行
            if (ProcessDispatcher.isrunning) {
                //                如果当前是闲逛进程
                if (pcb.getName().equals("闲逛进程") && ProcessDispatcher.getReadyProcessList().size() == 0 && ProcessDispatcher.getBlockedProcessList().size() != 0) {
                    System.out.println("补丁1生效了！！！");
                    awakeProcess();
                }
                if (pcb.getName().equals("闲逛进程") && ProcessDispatcher.getReadyProcessList().size() == 0 && ProcessDispatcher.getBlockedProcessList().size() == 0) {
                    for (PCB pcb : Memory.PCBlist) {
                        if (!pcb.getName().equals("闲逛进程")) {
                            ProcessDispatcher.getReadyProcessList().add(pcb);
                            System.out.println("补丁2生效了！！！");
                        }
                    }
                }
                System.out.println("当前正在运行====>" + pcb.getName());
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < Memory.PCBlist.size(); i++) {
                    stringBuilder.append(Memory.PCBlist.get(i).getName());
                }
                System.out.println("PCBList====>" + stringBuilder.toString());
                stringBuilder = new StringBuilder();
                for (int i = 0; i < ProcessDispatcher.getReadyProcessList().size(); i++) {
                    stringBuilder.append(ProcessDispatcher.getReadyProcessList().get(i).getName());
                }
                System.out.println("ReadyProcessList====>" + stringBuilder.toString());
                stringBuilder = new StringBuilder();
                for (int i = 0; i < ProcessDispatcher.getBlockedProcessList().size(); i++) {
                    stringBuilder.append(ProcessDispatcher.getBlockedProcessList().get(i).getName());
                }
                System.out.println("BlockedProcessList====>" + stringBuilder.toString());
//                如果被唤醒
                if (WakedUP) {
//                    启动调度线程
                    UpdatePCB();
                    return;
                }
//                如果正常中断，调度进程
                if (PSW == CPU.NORMAL_INTERMIT) {
                    //System.out.println(pcb.getProgress());
                    UpdatePCB();
                    return;
//                    如果时间片到中断，调度进程
                } else if (CPU.PSW == CPU.TIME_INTERMIT) {
                    UpdatePCB();
                    return;
                } else if (PSW == CPU.EQUIP_INTERMIT) {
//                    如果设备中断，调度进程
                    UpdatePCB();
                    return;
                }
//                从内存取程序计数器当前指令
                Instruction = MemoryDispatcher.fetchInstruction(PC);
                System.out.println("当前线程" + pcb.getName() + "执行的指令===>" + Instruction);
//                如果当前不是闲逛进程
                if (!pcb.getName().equals("闲逛进程")) {
//                    睡一秒模拟执行
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
//                设置指令寄存器内容
                for (int i = 0; i < 3; i++) IR[i] = Instruction.charAt(i);
                //执行一个指令
                char v = executeOrder();
//                剩余时间-1
                pcb.setResttime(pcb.getResttime() - 1);
//                设置进度
                pcb.setProgress(1 - (pcb.getResttime() / pcb.getRuntime()));
                //显示中间结果
                resultString = "";
//                如果当前cpu正在运行的线程pcb的变量表不为空
                if (!pcb.getVariableArea().isEmpty()) {
//                    输出当前变量表的变量和值
                    for (Map.Entry<Character, Integer> entry : pcb.getVariableArea().entrySet()) {
                        resultString += entry.getKey() + "=" + entry.getValue() + ";";
                    }
                }
                System.out.println("resultString=====》" + resultString);
//                cpu页面显示
                //记录运行记录
                if (!pcb.getName().equals("闲逛进程")) {
                    ProcessDispatcher.getProcessHistoryList().add(new ProcessHistory(
                            new SimpleDoubleProperty(ProcessDispatcher.getRunningtime()),
                            new SimpleStringProperty("正在执行"),
                            new SimpleStringProperty(pcb.getName()),
                            new SimpleStringProperty("剩余时间:" + pcb.getResttime()),
                            new SimpleStringProperty("中间结果:" + resultString)
                    ));
                } else {
//                    闲逛进程
                    pcb.setResttime(-1);
                }
                Platform.runLater(new Runnable() {
                    public void run() {
//                        运行指令
                        UI_CONTROLLER.getRunningOrder().setText(Instruction);
//                        运行进程
                        UI_CONTROLLER.getRunnningProcess().setText(pcb.getName());
//                        运行中间结果
                        UI_CONTROLLER.getTemporaryResults().setText(resultString);
//                        剩余时间
                        UI_CONTROLLER.getRemanTime().setText(String.valueOf(pcb.getResttime()));
                    }
                });
                //历史保存运行结果, 并展示在另一个页面


//                睡0.3秒
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
//                CPU执行时间片-1
                time--;
                //如果是当前CPU状态字是设备中断，运行调度线程
                if (CPU.PSW == CPU.EQUIP_INTERMIT) {
                    UpdatePCB();
                    return;
                }
                if (CPU.PSW == CPU.NORMAL_INTERMIT) {
                    return;
                }
                /*如果时间片到了而CPU还不是正常中断，就把CPU的PSW的状态设置成时间片结束中断,
                但是如果时间片到了，此时程序正好结束就把PSW设置成程序正常结束软中断，而忽略时间片结束中断*/
                if (time == 0 && CPU.PSW != CPU.NORMAL_INTERMIT) {
                    CPU.PSW = CPU.TIME_INTERMIT;
                }
//                PC指向下一条指令
                PC++;
            }
        }
    }

    private static char executeOrder() {
//        如果是end
        if (IR[0] == 'e' && IR[1] == 'n' && IR[2] == 'd') {
//            程序状态字设置正常中断
            PSW = CPU.NORMAL_INTERMIT;
            pcb.OutputResuit();
            if (!pcb.getName().equals("闲逛进程")) {
                destroyProcess();
            }
            return '&';
        } else if (IR[0] == '!') {
//            调度设备指令，设置PCB的PSW为阻塞
            Memory.setPCBToBlock(pcb.getName());
//            设置当前CPU状态字为设备中断
            PSW = CPU.EQUIP_INTERMIT;
//            设置cpu的pcb需要的设备
            pcb.setNeeddevice(IR[1]);
//            设置cpu的pcb需要占用设备的时间
            pcb.setHoldTime(IR[2] - '0');
            return '&';
        }//设备管理
        else {
//            普通指令
            char variable_name;
            int variable = 0;
//            从IR获得变量名
            variable_name = IR[0];
//            计算variable_name的结果variable
            if (IR[1] == '=') {
                variable = IR[2] - '0';
            } else if (IR[1] == '+') {
                variable = pcb.getVariableArea().get(variable_name) + 1;
            } else if (IR[1] == '-') {
                variable = pcb.getVariableArea().get(variable_name) - 1;
            }
//            更新变量表variable_name的值
            pcb.getVariableArea().put(variable_name, variable);
//            返回更新的变量
            return IR[0];
        }
    }

    private static void UpdatePCB() {
//        设置程序状态字
        pcb.setPSW(PSW);
        if (pcb.getName().equals("闲逛进程")) {
//            执行49指令
            PC = 49;
            pcb.setResttime(0.0);
        }
        pcb.setPC(PC);
    }

}